package pub.wkq.common.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import pub.wkq.common.exception.CustomException;
import pub.wkq.common.result.ResponseStatusEnum;

import javax.annotation.Resource;
import javax.crypto.SecretKey;
import java.util.Base64;
import java.util.Date;
import java.util.Objects;

/**
 * JWT 工具类
 *
 * @author: 王开琦
 * @date: 2021/9/15 22:19
 */
@Component
public class JWTUtils {
    public final static String at = "@";
    @Resource
    private JwtProperties jwtProperties;

    @Value("${jwt.key}")
    private String key;
    public String createJwtWithPrefix(String body, Long expireTime, String prefix) {
        if (expireTime == null) {
            CustomException.thr(ResponseStatusEnum.SYSTEM_NO_EXPIRE_ERROR);
        }
        return prefix + at + dealJwt(body, expireTime);
    }

    public String createJwtWithPrefix(String body, String prefix) {

        return prefix + at + dealJwt(body, null);
    }

    public String createJwt(String body) {
        return dealJwt(body, null);
    }

    public String createJwt(String body, Long expireTime) {
        if (expireTime == null) {
            CustomException.thr(ResponseStatusEnum.SYSTEM_NO_EXPIRE_ERROR);
        }
        return dealJwt(body, expireTime);
    }

    public String dealJwt(String body, Long expireTime) {
        //1. 对密钥进行base64编码
        byte[] base64 = Base64.getEncoder().encode(key.getBytes());
        //2. 对 base64 生成一个密钥的对象
        SecretKey secretKey = Keys.hmacShaKeyFor(base64);
        if (expireTime == null) {
            //不过期
            return generatorJWTDefault(body, secretKey);
        }
        return generatorJWTDefaultExpire(body, secretKey, expireTime);
    }

    /**
     *
     */
    public String generatorJWT(String body, SecretKey secretKey, long expireTime, String id, String issuer, String audience, Date notBefore, Date issuedAt) {
        String jwtTokenString = Jwts.builder()
                .setIssuer(issuer) //设置 jwt 签发者
                .setAudience(audience) //设置 jwt 接收者
                .setSubject(body)//设置用户自定义数据
                .setExpiration(new Date(System.currentTimeMillis() + expireTime)) //设置过期时间
                .setNotBefore(notBefore) //设置生效时间
                .setIssuedAt(issuedAt) //设置签发时间
                .setId(id) //设置 jwt 的唯一编号
                .signWith(secretKey) //设置加密算法和密钥
                .compact() //压缩并生成 jwt
                ;
        return jwtTokenString;
    }

    public String generatorJWTExpire(String body, SecretKey secretKey, long expireTime, String id, String issuer, String audience, Date notBefore, Date issuedAt) {
        String jwtTokenString = Jwts.builder()
                .setIssuer(issuer) //设置 jwt 签发者
                .setAudience(audience) //设置 jwt 接收者
                .setSubject(body)//设置用户自定义数据
                .setExpiration(new Date(System.currentTimeMillis() + expireTime)) //设置过期时间
                .setNotBefore(notBefore) //设置生效时间
                .setIssuedAt(issuedAt) //设置签发时间
                .setId(id) //设置 jwt 的唯一编号
                .signWith(secretKey) //设置加密算法和密钥
                .compact() //压缩并生成 jwt
                ;
        return jwtTokenString;
    }

    public String generatorJWTDefault(String body, SecretKey secretKey) {
        String jwtTokenString = Jwts.builder()
                .setSubject(body)//设置用户自定义数据
                .signWith(secretKey) //设置加密算法和密钥
                .compact() //压缩并生成 jwt
                ;
        return jwtTokenString;
    }

    public String generatorJWTDefaultExpire(String body, SecretKey secretKey, long expireTime) {
        String jwtTokenString = Jwts.builder()
                .setSubject(body)//设置用户自定义数据
                .setExpiration(new Date(System.currentTimeMillis() + expireTime)) //设置过期时间
                .signWith(secretKey) //设置加密算法和密钥
                .compact() //压缩并生成 jwt
                ;
        return jwtTokenString;
    }


    public  String checkJwt(String pendingJWT) {
        //模拟前端传过来的 jwt
        //1. 对密钥进行base64编码
        byte[] base64 = Base64.getEncoder().encode(key.getBytes());
        //2. 对 base64 生成一个密钥的对象
        SecretKey secretKey = Keys.hmacShaKeyFor(base64);
        //3. 解析 jwt
        JwtParser jwtParser = Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build(); //构造解析器

        //解析 jwt，解析的过程其实就是校验的过程
        Claims claims = jwtParser.parseClaimsJws(pendingJWT).getBody();
        return claims.getSubject();
    }
}
